﻿using System;
using System.Text;

namespace TI_BLE_HCI_ClientLib.DataEntities.Advertising
{
    public static class AdvertisingAndScanResponseDataParser
    {
        public static AdvertisingAndScanResponseData Parse(byte[] buffer)
        {
            byte idx = 0;

            AdvertisingAndScanResponseData advertisingAndScanResponseData = new AdvertisingAndScanResponseData();

            while (idx < buffer.Length-1)
            {
                addAdvertisingDataStructure(advertisingAndScanResponseData, buffer, ref idx);
            }

            return advertisingAndScanResponseData;
        }

        private static void addAdvertisingDataStructure(AdvertisingAndScanResponseData advertisingAndScanResponseData, byte[] buffer, ref byte idx)
        {
            byte adLen = buffer[idx];

            idx++;

            if (adLen == 0) return;

            AdvertisingDataStructureTypeEnum adType = (AdvertisingDataStructureTypeEnum)buffer[idx];

            idx++;

            switch (adType)
            {
                case AdvertisingDataStructureTypeEnum.Flags:
                    advertisingAndScanResponseData.addAdvertisingDataStructure(parseFlags(buffer, ref idx));
                    break;

                case AdvertisingDataStructureTypeEnum.ManufacturerSpecificData:
                    advertisingAndScanResponseData.addAdvertisingDataStructure(parseManufacturerSpecificData(buffer, (byte)(adLen - 1), ref idx));
                    break;

                case AdvertisingDataStructureTypeEnum.ShortenedLocalName:
                case AdvertisingDataStructureTypeEnum.CompleteLocalName:
                    advertisingAndScanResponseData.addAdvertisingDataStructure(parseLocalName(adType, buffer, (byte)(adLen - 1), ref idx));
                    break;

                case AdvertisingDataStructureTypeEnum.TxPowerLevel:
                    advertisingAndScanResponseData.addAdvertisingDataStructure(parseTxPowerLevel(buffer, ref idx));
                    break;

                case AdvertisingDataStructureTypeEnum.IncompleteListOf16BitServiceClassUUIDs:
                    advertisingAndScanResponseData.addAdvertisingDataStructure(parseIncompleteListOf16BitServiceClassUUIDs(buffer, (byte)(adLen - 1), ref idx));
                    break;

                default:
                    idx += (byte)(adLen - 1);
                    break;
            }
        }

        private static FlagsAdvertisingDataStructure parseFlags(byte[] buffer, ref byte idx)
        {
            FlagsAdvertisingDataStructure flags = new FlagsAdvertisingDataStructure((FlagsAdvertisingDataStructure.FlagsEnum)buffer[idx]);

            idx++;

            return flags;
        }

        private static ManufacturerSpecificDataAdvertisingDataStructure parseManufacturerSpecificData(byte[] buffer, byte len, ref byte idx)
        {
            byte[] arr = new byte[len];
            Array.Copy(buffer, idx, arr, 0, len);

            ManufacturerSpecificDataAdvertisingDataStructure manufacturerSpecificData = new ManufacturerSpecificDataAdvertisingDataStructure(arr);

            idx += len;

            return manufacturerSpecificData;
        }

        private static LocalNameAdvertisingDataStructure parseLocalName(AdvertisingDataStructureTypeEnum nameType, byte[] buffer, byte len, ref byte idx)
        {
            LocalNameAdvertisingDataStructure localName = new LocalNameAdvertisingDataStructure(nameType, new string(Encoding.UTF8.GetChars(buffer, idx, len)));

            idx += len;

            return localName;
        }

        private static TxPowerLevelAdvertisingDataStructure parseTxPowerLevel(byte[] buffer, ref byte idx)
        {
            TxPowerLevelAdvertisingDataStructure txPowerLevel = new TxPowerLevelAdvertisingDataStructure(buffer[idx]);

            idx++;

            return txPowerLevel;
        }

        private static IncompleteListOf16BitServiceUUIDsAdvertisingDataStructure parseIncompleteListOf16BitServiceClassUUIDs(byte[] buffer, byte len, ref byte idx)
        {
            ushort[] arr = new ushort[len/2];

            for(int i=0;i<len;i+=2)
            {
                arr[i / 2] = (ushort)(buffer[idx + i] + (buffer[idx + i + 1] << 8));
            }

            IncompleteListOf16BitServiceUUIDsAdvertisingDataStructure incompleteListOf16BitServiceUUIDs = new IncompleteListOf16BitServiceUUIDsAdvertisingDataStructure(arr);

            idx += len;

            return incompleteListOf16BitServiceUUIDs;
        }

    }
}